package com.tcl.mie.launcher.basehttp;

import android.text.TextUtils;

import com.squareup.okhttp.FormEncodingBuilder;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.MultipartBuilder;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.ResponseBody;

import java.io.File;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * Created by liwu.shu on 2016/7/8.
 */
public class HttpLoader {

    private final String TAG = HttpLoader.class.getSimpleName();
    private static final String MEDIA_TYPE = "application/octet-stream";
    String mUrl;
    State mState = State.None;
    HttpTask mCurrentTask;

    enum State {
        None, Begin, Loading, End
    }

    public HttpLoader(String url) {
        this.mUrl = url;
        mState = State.None;
    }

    public synchronized boolean load(HashMap<String, String> params, HashMap<String, byte[]> entityMap,
                                     HashMap<String, File> fileMaps, boolean isSupportPost) {
        if (mState != State.None && mState != State.End)
            throw new IllegalStateException("illegal state exception");

        if (TextUtils.isEmpty(mUrl)) {
            throw new NullPointerException("url can not be empty");
        }

        if (!NetworkHelper.sharedHelper().isNetworkAvailable()) {
            if (callback != null) {
                callback.onCompleted(HttpRequestResult.FAIL_CONNECT_TIMEOUT, null);
            }
            return false;
        }

        mState = State.Begin;
        Request request = createRequest(params, entityMap, fileMaps, isSupportPost);
        mCurrentTask = new HttpTask(request);
        mCurrentTask.setHttpCallback(callback);
        mCurrentTask.start();
        return false;
    }

    public synchronized void cancel() {
        if (mState == State.None || mState == State.End)
            return;

        if (mCurrentTask != null) {
            mCurrentTask.cancel();
        }
    }

    private Request createRequest(HashMap<String, String> params, HashMap<String, byte[]> entityMap,
                                  HashMap<String, File> fileMap, boolean isSupportPost) {
        if (!isSupportPost) {
            if (entityMap != null && entityMap.size() > 0) {
                //NLog.e(TAG, "http get not support post entity,ingore it");
            }
            return generateGetRequest(mUrl, params);
        }
        return generatePostRequest(mUrl, params, entityMap, fileMap);
    }

    private void onSuccess(ResponseBody body) {
        final LoadCallback callback = mCallBack;
        if (callback != null) {
            callback.onLoaded(HttpRequestResult.SUCCESS, body);
        }
    }

    private void onFail(int error) {
        final LoadCallback callback = mCallBack;
        if (callback != null) {
            callback.onLoaded(error, null);
        }
    }

    HttpTask.HttpCallback callback = new HttpTask.HttpCallback() {
        @Override
        public void onPrepared() {
            mState = State.Begin;
        }

        @Override
        public void onCompleted(int ret, ResponseBody responseBody) {
            mState = State.End;
            if (ret == HttpRequestResult.SUCCESS && responseBody != null) {
                onSuccess(responseBody);
            } else {
                onFail(ret);
            }
        }
    };

    LoadCallback mCallBack;

    public void setLoadCallback(LoadCallback callback) {
        this.mCallBack = callback;
    }

    public interface LoadCallback {
        void onLoaded(int err, ResponseBody entity);
    }

    private Request generateGetRequest(String url, HashMap<String, String> params) {
        int index = url.indexOf("?");
        StringBuilder sb = new StringBuilder();
        sb.append(url);
        Iterator<String> keyIterator = params.keySet().iterator();
        boolean isFirstAdd = true;
        while (keyIterator.hasNext()) {
            String key = keyIterator.next();
            String value = params.get(key);
            if (isFirstAdd) {
                if (index < 0) {
                    sb.append("?");
                } else if (index != url.length() - 1) {
                    sb.append("&");
                }
                isFirstAdd = false;
            } else {
                sb.append("&");
            }
            sb.append(key);
            sb.append("=");
            if (!TextUtils.isEmpty(value)) {
                String text = URLEncoder.encode(value);
                sb.append(text);
            }
        }
        String urlTxt = sb.toString();
        if (urlTxt.contains("+")) {
            urlTxt = urlTxt.replaceAll("\\+", "%20");
        }
        Request.Builder builder = new Request.Builder();
        builder.url(urlTxt);
        return builder.build();
    }

    private Request generatePostRequest(String url, HashMap<String, String> paramsMap, HashMap<String, byte[]> entityMap,
                                        HashMap<String, File> fileMap) {
        Request.Builder requestBuilder = new Request.Builder();
        requestBuilder.url(url);
        Request req = null;
        if ((entityMap == null || entityMap.size() == 0)
                && (fileMap == null || fileMap.size() == 0)) {
            FormEncodingBuilder builder = new FormEncodingBuilder();
            map2FormEncoding(paramsMap, builder);
            requestBuilder.post(builder.build());
            req = requestBuilder.build();
        } else {
            MultipartBuilder builder = new MultipartBuilder();
            builder.type(MultipartBuilder.FORM);

            // 处理字符参数
            Iterator<Map.Entry<String, String>> paramIterator = paramsMap
                    .entrySet().iterator();
            while (paramIterator.hasNext()) {
                Map.Entry<String, String> entry = paramIterator.next();
                String text = entry.getValue();
                if (text == null)
                    text = "";
                builder.addFormDataPart(entry.getKey(), text);
            }

            // 处理二进制数据
            if (entityMap != null && entityMap.size() > 0) {
                Iterator<Map.Entry<String, byte[]>> iterator = entityMap
                        .entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry<String, byte[]> entry = iterator.next();
                    String key = entry.getKey();
                    byte[] b = entry.getValue();
                    builder.addFormDataPart(key, null, RequestBody.create(null, b));
                }
            }

            // 处理文件数据
            if (fileMap != null && fileMap.size() > 0) {
                Iterator<Map.Entry<String, File>> fileIterator = fileMap
                        .entrySet().iterator();
                while (fileIterator.hasNext()) {
                    Map.Entry<String, File> entry = fileIterator.next();
                    String key = entry.getKey();
                    File b = entry.getValue();
                    builder.addFormDataPart(key, b.getName(), RequestBody.create(MediaType.parse(MEDIA_TYPE), b));
                }
            }
            requestBuilder.post(builder.build());
            req = requestBuilder.build();
        }
        return req;
    }


    private void map2FormEncoding(Map<String, String> paramsMap, FormEncodingBuilder build) {

        if (paramsMap == null || paramsMap.size() == 0)
            return;

        Iterator<Map.Entry<String, String>> iterator = paramsMap.entrySet()
                .iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, String> entry = iterator.next();
            String key = entry.getKey();
            String val = entry.getValue();
            if (TextUtils.isEmpty(key)) {
                key = "";
            }
            if (TextUtils.isEmpty(val)) {
                val = "";
            }
            build.add(key, val);
        }

    }
}
